#include "config.h"
#include "main.h"
#include "device.h"
void SysTick_init(void)
{

    /* setup systick timer for 1000Hz interrupts */
    if (SysTick_Config(SystemCoreClock / 1000U))
    {
        /* capture error */
        while (1)
        {
        }
    }

    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);

    /* re-define main function */
}

extern int $Super$$main(void);

void $Sub$$main(void)
{
   // nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x0000);
	SysTick_init();



    $Super$$main();
}

static void hard_fault_track(void);
static void usage_fault_track(void);
static void bus_fault_track(void);
static void mem_manage_fault_track(void);
#define uart_printf(x)
#define SCB_CFSR (*(volatile const unsigned *)0xE000ED28) /* Configurable Fault Status Register */
#define SCB_HFSR (*(volatile const unsigned *)0xE000ED2C) /* HardFault Status Register */
#define SCB_MMAR (*(volatile const unsigned *)0xE000ED34) /* MemManage Fault Address register */
#define SCB_BFAR (*(volatile const unsigned *)0xE000ED38) /* Bus Fault Address Register */
#define SCB_AIRCR (*(volatile unsigned long *)0xE000ED0C) /* Reset control Address Register */
#define SCB_RESET_VALUE 0x05FA0004                        /* Reset value, write to SCB_AIRCR can reset cpu */

#define SCB_CFSR_MFSR (*(volatile const unsigned char *)0xE000ED28)  /* Memory-management Fault Status Register */
#define SCB_CFSR_BFSR (*(volatile const unsigned char *)0xE000ED29)  /* Bus Fault Status Register */
#define SCB_CFSR_UFSR (*(volatile const unsigned short *)0xE000ED2A) /* Usage Fault Status Register */
static void hard_fault_track(void)
{
    if (SCB_HFSR & (1UL << 1))
    {
        /* [1]:VECTBL, Indicates hard fault is caused by failed vector fetch. */
        uart_printf("failed vector fetch\r\n");
    }

    if (SCB_HFSR & (1UL << 30))
    {
        /* [30]:FORCED, Indicates hard fault is taken because of bus fault,
                        memory management fault, or usage fault. */
        if (SCB_CFSR_BFSR)
        {
            bus_fault_track();
        }

        if (SCB_CFSR_MFSR)
        {
            mem_manage_fault_track();
        }

        if (SCB_CFSR_UFSR)
        {
            usage_fault_track();
        }
    }

    if (SCB_HFSR & (1UL << 31))
    {
        /* [31]:DEBUGEVT, Indicates hard fault is triggered by debug event. */
        uart_printf("debug event\r\n");
    }
}
static void usage_fault_track(void)
{
    //uart_printf("usage fault:SCB_CFSR_UFSR:0x%02X ", SCB_CFSR_UFSR);

    if (SCB_CFSR_UFSR & (1 << 0))
    {
        /* [0]:UNDEFINSTR */
        uart_printf("UNDEFINSTR ");
    }

    if (SCB_CFSR_UFSR & (1 << 1))
    {
        /* [1]:INVSTATE */
        uart_printf("INVSTATE ");
    }

    if (SCB_CFSR_UFSR & (1 << 2))
    {
        /* [2]:INVPC */
        uart_printf("INVPC ");
    }

    if (SCB_CFSR_UFSR & (1 << 3))
    {
        /* [3]:NOCP */
        uart_printf("NOCP ");
    }

    if (SCB_CFSR_UFSR & (1 << 8))
    {
        /* [8]:UNALIGNED */
        uart_printf("UNALIGNED ");
    }

    if (SCB_CFSR_UFSR & (1 << 9))
    {
        /* [9]:DIVBYZERO */
        uart_printf("DIVBYZERO ");
    }

    //    uart_printf("\r\n");
}

static void bus_fault_track(void)
{
    //uart_printf("bus fault: SCB_CFSR_BFSR:0x%02X ", SCB_CFSR_BFSR);

    if (SCB_CFSR_BFSR & (1 << 0))
    {
        /* [0]:IBUSERR */
        uart_printf("IBUSERR ");
    }

    if (SCB_CFSR_BFSR & (1 << 1))
    {
        /* [1]:PRECISERR */
        uart_printf("PRECISERR ");
    }

    if (SCB_CFSR_BFSR & (1 << 2))
    {
        /* [2]:IMPRECISERR */
        uart_printf("IMPRECISERR ");
    }

    if (SCB_CFSR_BFSR & (1 << 3))
    {
        /* [3]:UNSTKERR */
        uart_printf("UNSTKERR ");
    }

    if (SCB_CFSR_BFSR & (1 << 4))
    {
        /* [4]:STKERR */
        uart_printf("STKERR ");
    }

    if (SCB_CFSR_BFSR & (1 << 7))
    {
        //uart_printf("SCB->BFAR:%08X\r\n", SCB_BFAR);
    }
    else
    {
        //        uart_printf("\r\n");
    }
}

static void mem_manage_fault_track(void)
{
    //uart_printf("mem manage fault:SCB_CFSR_MFSR:0x%02X ", SCB_CFSR_MFSR);

    if (SCB_CFSR_MFSR & (1 << 0))
    {
        /* [0]:IACCVIOL */
        uart_printf("IACCVIOL ");
    }

    if (SCB_CFSR_MFSR & (1 << 1))
    {
        /* [1]:DACCVIOL */
        uart_printf("DACCVIOL ");
    }

    if (SCB_CFSR_MFSR & (1 << 3))
    {
        /* [3]:MUNSTKERR */
        uart_printf("MUNSTKERR ");
    }

    if (SCB_CFSR_MFSR & (1 << 4))
    {
        /* [4]:MSTKERR */
        uart_printf("MSTKERR ");
    }

    if (SCB_CFSR_MFSR & (1 << 7))
    {
        /* [7]:MMARVALID */
        //uart_printf("SCB->MMAR:%08X\r\n", SCB_MMAR);
    }
    else
    {
        //        uart_printf("\r\n");
    }
}

struct exception_stack_frame
{
    uint32_t r0;
    uint32_t r1;
    uint32_t r2;
    uint32_t r3;
    uint32_t r12;
    uint32_t lr;
    uint32_t pc;
    uint32_t psr;
};

struct exception_info
{
    uint32_t r4;
    uint32_t r5;
    uint32_t r6;
    uint32_t r7;
    uint32_t r8;
    uint32_t r9;
    uint32_t r10;
    uint32_t r11;

    struct exception_stack_frame exception_stack_frame;
};
void hard_fault(struct exception_info *context)
{
    //	uart_printf("psr: 0x%08x\r\n", context->exception_stack_frame.psr);
    //    uart_printf("r00: 0x%08x\r\n", context->exception_stack_frame.r0);
    //    uart_printf("r01: 0x%08x\r\n", context->exception_stack_frame.r1);
    //    uart_printf("r02: 0x%08x\r\n", context->exception_stack_frame.r2);
    //    uart_printf("r03: 0x%08x\r\n", context->exception_stack_frame.r3);
    //    uart_printf("r04: 0x%08x\r\n", context->r4);
    //    uart_printf("r05: 0x%08x\r\n", context->r5);
    //    uart_printf("r06: 0x%08x\r\n", context->r6);
    //    uart_printf("r07: 0x%08x\r\n", context->r7);
    //    uart_printf("r08: 0x%08x\r\n", context->r8);
    //    uart_printf("r09: 0x%08x\r\n", context->r9);
    //    uart_printf("r10: 0x%08x\r\n", context->r10);
    //    uart_printf("r11: 0x%08x\r\n", context->r11);
    //    uart_printf("r12: 0x%08x\r\n", context->exception_stack_frame.r12);
    //uart_printf(" lr: 0x%08x\r\n", context->exception_stack_frame.lr); // һ����������ڴ˵�ַ���ڵĴ���
    //uart_printf(" pc: 0x%08x\r\n", context->exception_stack_frame.pc);
    //uart_printf("hardfault lr: 0x%08x\r\n", context->exception_stack_frame.lr);
    //    uart_printf("hard fault on handler\r\n");
    hard_fault_track();
    while (1)
        ;
}
